home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / tk2.3 / dist / tkCanvPoly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-28  |  21.9 KB  |  771 lines

  1. /* 
  2.  * tkCanvPoly.c --
  3.  *
  4.  *    This file implements polygon items for canvas widgets.
  5.  *
  6.  * Copyright 1991-1992 Regents of the University of California.
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkCanvPoly.c,v 1.6 92/07/28 15:40:10 ouster Exp $ SPRITE (Berkeley)";
  18. #endif
  19.  
  20. #include <stdio.h>
  21. #include <math.h>
  22. #include "tkInt.h"
  23. #include "tkCanvas.h"
  24. #include "tkConfig.h"
  25.  
  26. /*
  27.  * The structure below defines the record for each polygon item.
  28.  */
  29.  
  30. typedef struct PolygonItem  {
  31.     Tk_Item header;        /* Generic stuff that's the same for all
  32.                  * types.  MUST BE FIRST IN STRUCTURE. */
  33.     int numPoints;        /* Number of points in polygon (always >= 3).
  34.                  * Polygon is always closed. */
  35.     double *coordPtr;        /* Pointer to malloc-ed array containing
  36.                  * x- and y-coords of all points in polygon.
  37.                  * X-coords are even-valued indices, y-coords
  38.                  * are corresponding odd-valued indices. */
  39.     XColor *fg;            /* Foreground color for polygon. */
  40.     Pixmap fillStipple;        /* Stipple bitmap for filling polygon. */
  41.     GC gc;            /* Graphics context for filling polygon. */
  42.     int smooth;            /* Non-zero means draw shape smoothed (i.e.
  43.                  * with Bezier splines). */
  44.     int splineSteps;        /* Number of steps in each spline segment. */
  45. } PolygonItem;
  46.  
  47. /*
  48.  * Information used for parsing configuration specs:
  49.  */
  50.  
  51. static Tk_ConfigSpec configSpecs[] = {
  52.     {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
  53.     "black", Tk_Offset(PolygonItem, fg), TK_CONFIG_NULL_OK},
  54.     {TK_CONFIG_BOOLEAN, "-smooth", (char *) NULL, (char *) NULL,
  55.     "no", Tk_Offset(PolygonItem, smooth), TK_CONFIG_DONT_SET_DEFAULT},
  56.     {TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,
  57.     "12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},
  58.     {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
  59.     (char *) NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK},
  60.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  61.     (char *) NULL, 0, TK_CONFIG_NULL_OK, &tkCanvasTagsOption},
  62.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  63.     (char *) NULL, 0, 0}
  64. };
  65.  
  66. /*
  67.  * Prototypes for procedures defined in this file:
  68.  */
  69.  
  70. static void        ComputePolygonBbox _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  71.                 PolygonItem *polyPtr));
  72. static int        ConfigurePolygon _ANSI_ARGS_((
  73.                 Tk_Canvas *canvasPtr, Tk_Item *itemPtr, int argc,
  74.                 char **argv, int flags));
  75. static int        CreatePolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  76.                 struct Tk_Item *itemPtr, int argc, char **argv));
  77. static void        DeletePolygon _ANSI_ARGS_((Tk_Item *itemPtr));
  78. static void        DisplayPolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  79.                 Tk_Item *itemPtr, Drawable dst));
  80. static int        PolygonCoords _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  81.                 Tk_Item *itemPtr, int argc, char **argv));
  82. static int        PolygonToArea _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  83.                 Tk_Item *itemPtr, double *rectPtr));
  84. static double        PolygonToPoint _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  85.                 Tk_Item *itemPtr, double *pointPtr));
  86. static void        ScalePolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  87.                 Tk_Item *itemPtr, double originX, double originY,
  88.                 double scaleX, double scaleY));
  89. static void        TranslatePolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
  90.                 Tk_Item *itemPtr, double deltaX, double deltaY));
  91.  
  92. /*
  93.  * The structures below defines the polygon item type by means
  94.  * of procedures that can be invoked by generic item code.
  95.  */
  96.  
  97. Tk_ItemType TkPolygonType = {
  98.     "polygon",                /* name */
  99.     sizeof(PolygonItem),        /* itemSize */
  100.     CreatePolygon,            /* createProc */
  101.     configSpecs,            /* configSpecs */
  102.     ConfigurePolygon,            /* configureProc */
  103.     PolygonCoords,            /* coordProc */
  104.     DeletePolygon,            /* deleteProc */
  105.     DisplayPolygon,            /* displayProc */
  106.     0,                    /* alwaysRedraw */
  107.     PolygonToPoint,            /* pointProc */
  108.     PolygonToArea,            /* areaProc */
  109.     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
  110.     ScalePolygon,            /* scaleProc */
  111.     TranslatePolygon,            /* translateProc */
  112.     (Tk_ItemIndexProc *) NULL,        /* indexProc */
  113.     (Tk_ItemCursorProc *) NULL,        /* cursorProc */
  114.     (Tk_ItemSelectionProc *) NULL,    /* selectionProc */
  115.     (Tk_ItemInsertProc *) NULL,        /* insertProc */
  116.     (Tk_ItemDCharsProc *) NULL,        /* dTextProc */
  117.     (Tk_ItemType *) NULL        /* nextPtr */
  118. };
  119.  
  120. /*
  121.  * The definition below determines how large are static arrays
  122.  * used to hold spline points (splines larger than this have to
  123.  * have their arrays malloc-ed).
  124.  */
  125.  
  126. #define MAX_STATIC_POINTS 200
  127.  
  128. /*
  129.  *--------------------------------------------------------------
  130.  *
  131.  * CreatePolygon --
  132.  *
  133.  *    This procedure is invoked to create a new polygon item in
  134.  *    a canvas.
  135.  *
  136.  * Results:
  137.  *    A standard Tcl return value.  If an error occurred in
  138.  *    creating the item, then an error message is left in
  139.  *    canvasPtr->interp->result;  in this case itemPtr is
  140.  *    left uninitialized, so it can be safely freed by the
  141.  *    caller.
  142.  *
  143.  * Side effects:
  144.  *    A new polygon item is created.
  145.  *
  146.  *--------------------------------------------------------------
  147.  */
  148.  
  149. static int
  150. CreatePolygon(canvasPtr, itemPtr, argc, argv)
  151.     register Tk_Canvas *canvasPtr;    /* Canvas to hold new item. */
  152.     Tk_Item *itemPtr;            /* Record to hold new item;  header
  153.                      * has been initialized by caller. */
  154.     int argc;                /* Number of arguments in argv. */
  155.     char **argv;            /* Arguments describing polygon. */
  156. {
  157.     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  158.     int i;
  159.  
  160.     if (argc < 6) {
  161.     Tcl_AppendResult(canvasPtr->interp, "wrong # args:  should be \"",
  162.         Tk_PathName(canvasPtr->tkwin),
  163.         "\" create x1 y1 x2 y2 x3 y3 ?x4 y4 ...? ?options?",
  164.         (char *) NULL);
  165.     return TCL_ERROR;
  166.     }
  167.  
  168.     /*
  169.      * Carry out initialization that is needed in order to clean
  170.      * up after errors during the the remainder of this procedure.
  171.      */
  172.  
  173.     polyPtr->numPoints = 0;
  174.     polyPtr->coordPtr = NULL;
  175.     polyPtr->fg = None;
  176.     polyPtr->fillStipple = None;
  177.     polyPtr->gc = None;
  178.     polyPtr->smooth = 0;
  179.     polyPtr->splineSteps = 12;
  180.  
  181.     /*
  182.      * Count the number of points and then parse them into a point
  183.      * array.  Leading arguments are assumed to be points if they
  184.      * start with a digit or a minus sign followed by a digit.
  185.      */
  186.  
  187.     for (i = 4; i < (argc-1); i+=2) {
  188.     if ((!isdigit(argv[i][0])) &&
  189.         ((argv[i][0] != '-') || (!isdigit(argv[i][1])))) {
  190.         break;
  191.     }
  192.     }
  193.     if (PolygonCoords(canvasPtr, itemPtr, i, argv) != TCL_OK) {
  194.     goto error;
  195.     }
  196.  
  197.     if (ConfigurePolygon(canvasPtr, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
  198.     return TCL_OK;
  199.     }
  200.  
  201.     error:
  202.     DeletePolygon(itemPtr);
  203.     return TCL_ERROR;
  204. }
  205.  
  206. /*
  207.  *--------------------------------------------------------------
  208.  *
  209.  * PolygonCoords --
  210.  *
  211.  *    This procedure is invoked to process the "coords" widget
  212.  *    command on polygons.  See the user documentation for details
  213.  *    on what it does.
  214.  *
  215.  * Results:
  216.  *    Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
  217.  *
  218.  * Side effects:
  219.  *    The coordinates for the given item may be changed.
  220.  *
  221.  *--------------------------------------------------------------
  222.  */
  223.  
  224. static int
  225. PolygonCoords(canvasPtr, itemPtr, argc, argv)
  226.     register Tk_Canvas *canvasPtr;    /* Canvas containing item. */
  227.     Tk_Item *itemPtr;            /* Item whose coordinates are to be
  228.                      * read or modified. */
  229.     int argc;                /* Number of coordinates supplied in
  230.                      * argv. */
  231.     char **argv;            /* Array of coordinates: x1, y1,
  232.                      * x2, y2, ... */
  233. {
  234.     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  235.     char buffer[300];
  236.     int i, numPoints;
  237.  
  238.     if (argc == 0) {
  239.     for (i = 0; i < 2*polyPtr->numPoints; i++) {
  240.         sprintf(buffer, "%g", polyPtr->coordPtr[i]);
  241.         Tcl_AppendElement(canvasPtr->interp, buffer, 0);
  242.     }
  243.     } else if (argc < 6) {
  244.     Tcl_AppendResult(canvasPtr->interp,
  245.         "too few coordinates for polygon:  must have at least 6",
  246.         (char *) NULL);
  247.     return TCL_ERROR;
  248.     } else if (argc & 1) {
  249.     Tcl_AppendResult(canvasPtr->interp,
  250.         "odd number of coordinates specified for polygon",
  251.         (char *) NULL);
  252.     return TCL_ERROR;
  253.     } else {
  254.     numPoints = argc/2;
  255.     if (polyPtr->numPoints != numPoints) {
  256.         if (polyPtr->coordPtr != NULL) {
  257.         ckfree((char *) polyPtr->coordPtr);
  258.         }
  259.  
  260.         /*
  261.          * One extra point gets allocated here, just in case we have
  262.          * to add another point to close the polygon.
  263.          */
  264.  
  265.         polyPtr->coordPtr = (double *) ckalloc((unsigned)
  266.             (sizeof(double) * (argc+2)));
  267.         polyPtr->numPoints = numPoints;
  268.     }
  269.     for (i = argc-1; i >= 0; i--) {
  270.         if (TkGetCanvasCoord(canvasPtr, argv[i], &polyPtr->coordPtr[i])
  271.             != TCL_OK) {
  272.         return TCL_ERROR;
  273.         }
  274.     }
  275.     
  276.     /*
  277.      * Close the polygon if it isn't already closed.
  278.      */
  279.     
  280.     if ((polyPtr->coordPtr[argc-2] != polyPtr->coordPtr[0])
  281.         || (polyPtr->coordPtr[argc-1] != polyPtr->coordPtr[1])) {
  282.         polyPtr->numPoints++;
  283.         polyPtr->coordPtr[argc] = polyPtr->coordPtr[0];
  284.         polyPtr->coordPtr[argc+1] = polyPtr->coordPtr[1];
  285.     }
  286.     ComputePolygonBbox(canvasPtr, polyPtr);
  287.     }
  288.     return TCL_OK;
  289. }
  290.  
  291. /*
  292.  *--------------------------------------------------------------
  293.  *
  294.  * ConfigurePolygon --
  295.  *
  296.  *    This procedure is invoked to configure various aspects
  297.  *    of a polygon item such as its background color.
  298.  *
  299.  * Results:
  300.  *    A standard Tcl result code.  If an error occurs, then
  301.  *    an error message is left in canvasPtr->interp->result.
  302.  *
  303.  * Side effects:
  304.  *    Configuration information, such as colors and stipple
  305.  *    patterns, may be set for itemPtr.
  306.  *
  307.  *--------------------------------------------------------------
  308.  */
  309.  
  310. static int
  311. ConfigurePolygon(canvasPtr, itemPtr, argc, argv, flags)
  312.     Tk_Canvas *canvasPtr;    /* Canvas containing itemPtr. */
  313.     Tk_Item *itemPtr;        /* Polygon item to reconfigure. */
  314.     int argc;            /* Number of elements in argv.  */
  315.     char **argv;        /* Arguments describing things to configure. */
  316.     int flags;            /* Flags to pass to Tk_ConfigureWidget. */
  317. {
  318.     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  319.     XGCValues gcValues;
  320.     GC newGC;
  321.     unsigned long mask;
  322.  
  323.     if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
  324.         configSpecs, argc, argv, (char *) polyPtr, flags) != TCL_OK) {
  325.     return TCL_ERROR;
  326.     }
  327.  
  328.     /*
  329.      * A few of the options require additional processing, such as
  330.      * graphics contexts.
  331.      */
  332.  
  333.     if (polyPtr->fg == NULL) {
  334.     newGC = None;
  335.     } else {
  336.     gcValues.foreground = polyPtr->fg->pixel;
  337.     mask = GCForeground;
  338.     if (polyPtr->fillStipple != None) {
  339.         gcValues.stipple = polyPtr->fillStipple;
  340.         gcValues.fill_style = FillStippled;
  341.         mask |= GCStipple|GCFillStyle;
  342.     }
  343.     newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
  344.     }
  345.     if (polyPtr->gc != None) {
  346.     Tk_FreeGC(polyPtr->gc);
  347.     }
  348.     polyPtr->gc = newGC;
  349.  
  350.     /*
  351.      * Keep spline parameters within reasonable limits.
  352.      */
  353.  
  354.     if (polyPtr->splineSteps < 1) {
  355.     polyPtr->splineSteps = 1;
  356.     } else if (polyPtr->splineSteps > 100) {
  357.     polyPtr->splineSteps = 100;
  358.     }
  359.  
  360.     ComputePolygonBbox(canvasPtr, polyPtr);
  361.     return TCL_OK;
  362. }
  363.  
  364. /*
  365.  *--------------------------------------------------------------
  366.  *
  367.  * DeletePolygon --
  368.  *
  369.  *    This procedure is called to clean up the data structure
  370.  *    associated with a polygon item.
  371.  *
  372.  * Results:
  373.  *    None.
  374.  *
  375.  * Side effects:
  376.  *    Resources associated with itemPtr are released.
  377.  *
  378.  *--------------------------------------------------------------
  379.  */
  380.  
  381. static void
  382. DeletePolygon(itemPtr)
  383.     Tk_Item *itemPtr;            /* Item that is being deleted. */
  384. {
  385.     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  386.  
  387.     if (polyPtr->coordPtr != NULL) {
  388.     ckfree((char *) polyPtr->coordPtr);
  389.     }
  390.     if (polyPtr->fg != NULL) {
  391.     Tk_FreeColor(polyPtr->fg);
  392.     }
  393.     if (polyPtr->fillStipple != None) {
  394.     Tk_FreeBitmap(polyPtr->fillStipple);
  395.     }
  396.     if (polyPtr->gc != None) {
  397.     Tk_FreeGC(polyPtr->gc);
  398.     }
  399. }
  400.  
  401. /*
  402.  *--------------------------------------------------------------
  403.  *
  404.  * ComputePolygonBbox --
  405.  *
  406.  *    This procedure is invoked to compute the bounding box of
  407.  *    all the pixels that may be drawn as part of a polygon.
  408.  *
  409.  * Results:
  410.  *    None.
  411.  *
  412.  * Side effects:
  413.  *    The fields x1, y1, x2, and y2 are updated in the header
  414.  *    for itemPtr.
  415.  *
  416.  *--------------------------------------------------------------
  417.  */
  418.  
  419. static void
  420. ComputePolygonBbox(canvasPtr, polyPtr)
  421.     register Tk_Canvas *canvasPtr;    /* Canvas that contains item. */
  422.     PolygonItem *polyPtr;        /* Item whose bbox is to be
  423.                      * recomputed. */
  424. {
  425.     register double *coordPtr;
  426.     int i;
  427.  
  428.     coordPtr = polyPtr->coordPtr;
  429.     polyPtr->header.x1 = polyPtr->header.x2 = *coordPtr;
  430.     polyPtr->header.y1 = polyPtr->header.y2 = coordPtr[1];
  431.  
  432.     for (i = 1, coordPtr = polyPtr->coordPtr+2; i < polyPtr->numPoints;
  433.         i++, coordPtr += 2) {
  434.     TkIncludePoint(canvasPtr, (Tk_Item *) polyPtr, coordPtr);
  435.     }
  436.  
  437.     /*
  438.      * Add one more pixel of fudge factor just to be safe (e.g.
  439.      * X may round differently than we do).
  440.      */
  441.  
  442.     polyPtr->header.x1 -= 1;
  443.     polyPtr->header.x2 += 1;
  444.     polyPtr->header.y1 -= 1;
  445.     polyPtr->header.y2 += 1;
  446. }
  447.  
  448. /*
  449.  *--------------------------------------------------------------
  450.  *
  451.  * TkFillPolygon --
  452.  *
  453.  *    This procedure is invoked to convert a polygon to screen
  454.  *    coordinates and display it using a particular GC.
  455.  *
  456.  * Results:
  457.  *    None.
  458.  *
  459.  * Side effects:
  460.  *    ItemPtr is drawn in drawable using the transformation
  461.  *    information in canvasPtr.
  462.  *
  463.  *--------------------------------------------------------------
  464.  */
  465.  
  466. void
  467. TkFillPolygon(canvasPtr, coordPtr, numPoints, drawable, gc)
  468.     register Tk_Canvas *canvasPtr;    /* Canvas whose coordinate system
  469.                      * is to be used for drawing. */
  470.     double *coordPtr;            /* Array of coordinates for polygon:
  471.                      * x1, y1, x2, y2, .... */
  472.     int numPoints;            /* Twice this many coordinates are
  473.                      * present at *coordPtr. */
  474.     Drawable drawable;            /* Pixmap or window in which to draw
  475.                      * polygon. */
  476.     GC gc;                /* Graphics context for drawing. */
  477. {
  478.     XPoint staticPoints[MAX_STATIC_POINTS];
  479.     XPoint *pointPtr;
  480.     register XPoint *pPtr;
  481.     int i;
  482.  
  483.     /*
  484.      * Build up an array of points in screen coordinates.  Use a
  485.      * static array unless the polygon has an enormous number of points;
  486.      * in this case, dynamically allocate an array.
  487.      */
  488.  
  489.     if (numPoints <= MAX_STATIC_POINTS) {
  490.     pointPtr = staticPoints;
  491.     } else {
  492.     pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint)));
  493.     }
  494.  
  495.     for (i = 0, pPtr = pointPtr; i < numPoints; i += 1, coordPtr += 2, pPtr++) {
  496.     pPtr->x = SCREEN_X(canvasPtr, coordPtr[0]);
  497.     pPtr->y = SCREEN_Y(canvasPtr, coordPtr[1]);
  498.     }
  499.  
  500.     /*
  501.      * Display polygon, then free up polygon storage if it was dynamically
  502.      * allocated.
  503.      */
  504.  
  505.     XFillPolygon(Tk_Display(canvasPtr->tkwin), drawable, gc, pointPtr,
  506.         numPoints, Complex, CoordModeOrigin);
  507.     if (pointPtr != staticPoints) {
  508.     ckfree((char *) pointPtr);
  509.     }
  510.  
  511. }
  512.  
  513. /*
  514.  *--------------------------------------------------------------
  515.  *
  516.  * DisplayPolygon --
  517.  *
  518.  *    This procedure is invoked to draw a polygon item in a given
  519.  *    drawable.
  520.  *
  521.  * Results:
  522.  *    None.
  523.  *
  524.  * Side effects:
  525.  *    ItemPtr is drawn in drawable using the transformation
  526.  *    information in canvasPtr.
  527.  *
  528.  *--------------------------------------------------------------
  529.  */
  530.  
  531. static void
  532. DisplayPolygon(canvasPtr, itemPtr, drawable)
  533.     register Tk_Canvas *canvasPtr;    /* Canvas that contains item. */
  534.     Tk_Item *itemPtr;            /* Item to be displayed. */
  535.     Drawable drawable;            /* Pixmap or window in which to draw
  536.                      * item. */
  537. {
  538.     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  539.  
  540.     if (polyPtr->gc == None) {
  541.     return;
  542.     }
  543.  
  544.     if (!polyPtr->smooth) {
  545.     TkFillPolygon(canvasPtr, polyPtr->coordPtr, polyPtr->numPoints,
  546.         drawable, polyPtr->gc);
  547.     } else {
  548.     int numPoints;
  549.     XPoint staticPoints[MAX_STATIC_POINTS];
  550.     XPoint *pointPtr;
  551.  
  552.     /*
  553.      * This is a smoothed polygon.  Display using a set of generated
  554.      * spline points rather than the original points.
  555.      */
  556.  
  557.     numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
  558.     if (numPoints <= MAX_STATIC_POINTS) {
  559.         pointPtr = staticPoints;
  560.     } else {
  561.         pointPtr = (XPoint *) ckalloc((unsigned)
  562.             (numPoints * sizeof(XPoint)));
  563.     }
  564.     numPoints = TkMakeBezierCurve(canvasPtr, polyPtr->coordPtr,
  565.         polyPtr->numPoints, polyPtr->splineSteps, pointPtr,
  566.         (double *) NULL);
  567.     XFillPolygon(Tk_Display(canvasPtr->tkwin), drawable, polyPtr->gc,
  568.         pointPtr, numPoints, Complex, CoordModeOrigin);
  569.     if (pointPtr != staticPoints) {
  570.         ckfree((char *) pointPtr);
  571.     }
  572.     }
  573. }
  574.  
  575. /*
  576.  *--------------------------------------------------------------
  577.  *
  578.  * PolygonToPoint --
  579.  *
  580.  *    Computes the distance from a given point to a given
  581.  *    polygon, in canvas units.
  582.  *
  583.  * Results:
  584.  *    The return value is 0 if the point whose x and y coordinates
  585.  *    are pointPtr[0] and pointPtr[1] is inside the polygon.  If the
  586.  *    point isn't inside the polygon then the return value is the
  587.  *    distance from the point to the polygon.
  588.  *
  589.  * Side effects:
  590.  *    None.
  591.  *
  592.  *--------------------------------------------------------------
  593.  */
  594.  
  595.     /* ARGSUSED */
  596. static double
  597. PolygonToPoint(canvasPtr, itemPtr, pointPtr)
  598.     Tk_Canvas *canvasPtr;    /* Canvas containing item. */
  599.     Tk_Item *itemPtr;        /* Item to check against point. */
  600.     double *pointPtr;        /* Pointer to x and y coordinates. */
  601. {
  602.     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  603.     double *coordPtr, distance;
  604.     double staticSpace[2*MAX_STATIC_POINTS];
  605.     int numPoints;
  606.  
  607.     if (!polyPtr->smooth) {
  608.     return TkPolygonToPoint(polyPtr->coordPtr, polyPtr->numPoints,
  609.         pointPtr);
  610.     }
  611.  
  612.     /*
  613.      * Smoothed polygon.  Generate a new set of points and use them
  614.      * for comparison.
  615.      */
  616.  
  617.     numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
  618.     if (numPoints <= MAX_STATIC_POINTS) {
  619.     coordPtr = staticSpace;
  620.     } else {
  621.     coordPtr = (double *) ckalloc((unsigned)
  622.         (2*numPoints*sizeof(double)));
  623.     }
  624.     numPoints = TkMakeBezierCurve(canvasPtr, polyPtr->coordPtr,
  625.         polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
  626.         coordPtr);
  627.     distance = TkPolygonToPoint(coordPtr, numPoints, pointPtr);
  628.     if (coordPtr != staticSpace) {
  629.     ckfree((char *) coordPtr);
  630.     }
  631.     return distance;
  632. }
  633.  
  634. /*
  635.  *--------------------------------------------------------------
  636.  *
  637.  * PolygonToArea --
  638.  *
  639.  *    This procedure is called to determine whether an item
  640.  *    lies entirely inside, entirely outside, or overlapping
  641.  *    a given rectangular area.
  642.  *
  643.  * Results:
  644.  *    -1 is returned if the item is entirely outside the area
  645.  *    given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  646.  *    inside the given area.
  647.  *
  648.  * Side effects:
  649.  *    None.
  650.  *
  651.  *--------------------------------------------------------------
  652.  */
  653.  
  654.     /* ARGSUSED */
  655. static int
  656. PolygonToArea(canvasPtr, itemPtr, rectPtr)
  657.     Tk_Canvas *canvasPtr;    /* Canvas containing item. */
  658.     Tk_Item *itemPtr;        /* Item to check against polygon. */
  659.     double *rectPtr;        /* Pointer to array of four coordinates
  660.                  * (x1, y1, x2, y2) describing rectangular
  661.                  * area.  */
  662. {
  663.     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  664.     double *coordPtr;
  665.     double staticSpace[2*MAX_STATIC_POINTS];
  666.     int numPoints, result;
  667.  
  668.     if (!polyPtr->smooth) {
  669.     return TkPolygonToArea(polyPtr->coordPtr, polyPtr->numPoints, rectPtr);
  670.     }
  671.  
  672.     /*
  673.      * Smoothed polygon.  Generate a new set of points and use them
  674.      * for comparison.
  675.      */
  676.  
  677.     numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
  678.     if (numPoints <= MAX_STATIC_POINTS) {
  679.     coordPtr = staticSpace;
  680.     } else {
  681.     coordPtr = (double *) ckalloc((unsigned)
  682.         (2*numPoints*sizeof(double)));
  683.     }
  684.     numPoints = TkMakeBezierCurve(canvasPtr, polyPtr->coordPtr,
  685.         polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
  686.         coordPtr);
  687.     result = TkPolygonToArea(coordPtr, numPoints, rectPtr);
  688.     if (coordPtr != staticSpace) {
  689.     ckfree((char *) coordPtr);
  690.     }
  691.     return result;
  692. }
  693.  
  694. /*
  695.  *--------------------------------------------------------------
  696.  *
  697.  * ScalePolygon --
  698.  *
  699.  *    This procedure is invoked to rescale a polygon item.
  700.  *
  701.  * Results:
  702.  *    None.
  703.  *
  704.  * Side effects:
  705.  *    The polygon referred to by itemPtr is rescaled so that the
  706.  *    following transformation is applied to all point
  707.  *    coordinates:
  708.  *        x' = originX + scaleX*(x-originX)
  709.  *        y' = originY + scaleY*(y-originY)
  710.  *
  711.  *--------------------------------------------------------------
  712.  */
  713.  
  714. static void
  715. ScalePolygon(canvasPtr, itemPtr, originX, originY, scaleX, scaleY)
  716.     Tk_Canvas *canvasPtr;        /* Canvas containing polygon. */
  717.     Tk_Item *itemPtr;            /* Polygon to be scaled. */
  718.     double originX, originY;        /* Origin about which to scale rect. */
  719.     double scaleX;            /* Amount to scale in X direction. */
  720.     double scaleY;            /* Amount to scale in Y direction. */
  721. {
  722.     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  723.     register double *coordPtr;
  724.     int i;
  725.  
  726.     for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
  727.         i++, coordPtr += 2) {
  728.     *coordPtr = originX + scaleX*(*coordPtr - originX);
  729.     coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
  730.     }
  731.     ComputePolygonBbox(canvasPtr, polyPtr);
  732. }
  733.  
  734. /*
  735.  *--------------------------------------------------------------
  736.  *
  737.  * TranslatePolygon --
  738.  *
  739.  *    This procedure is called to move a polygon by a given
  740.  *    amount.
  741.  *
  742.  * Results:
  743.  *    None.
  744.  *
  745.  * Side effects:
  746.  *    The position of the polygon is offset by (xDelta, yDelta),
  747.  *    and the bounding box is updated in the generic part of the
  748.  *    item structure.
  749.  *
  750.  *--------------------------------------------------------------
  751.  */
  752.  
  753. static void
  754. TranslatePolygon(canvasPtr, itemPtr, deltaX, deltaY)
  755.     Tk_Canvas *canvasPtr;        /* Canvas containing item. */
  756.     Tk_Item *itemPtr;            /* Item that is being moved. */
  757.     double deltaX, deltaY;        /* Amount by which item is to be
  758.                      * moved. */
  759. {
  760.     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
  761.     register double *coordPtr;
  762.     int i;
  763.  
  764.     for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
  765.         i++, coordPtr += 2) {
  766.     *coordPtr += deltaX;
  767.     coordPtr[1] += deltaY;
  768.     }
  769.     ComputePolygonBbox(canvasPtr, polyPtr);
  770. }
  771.